//
//  PayManager.m
//  LingVR
//
//  Created by MinLison on 16/7/4.
//  Copyright © 2016年 LingVR. All rights reserved.
//

#import "PayManager.h"


#define kUrlScheme      @""

#define kPingAppID      @""


NSString *PayCancelResult = @"cancel";
NSString *PaySuccessResult = @"success";

NSString *ErrorDesForCode(NSInteger errorCode)
{
        NSString *errorDes = @"未知错误";
        switch (errorCode) {
                case PayiTunesErrorCodeUnknown: {
                        errorDes = @"无法连接到 iTunes Store";
                        break;
                }
                case PayiTunesErrorCodeClientInvalid: {
                        errorDes = @"无效请求";
                        break;
                }
                case PayiTunesErrorCodePaymentCancelled: {
                        errorDes = @"取消购买";
                        break;
                }
                case PayiTunesErrorCodePaymentInvalid: {
                        errorDes = @"未知商品";
                        break;
                }
                case PayiTunesErrorCodePaymentNotAllowed: {
                        errorDes = @"设备不支持内购";
                        break;
                }
                case PayiTunesErrorCodeStoreProductNotAvailable: {
                        errorDes = @"无效商品";
                        break;
                }
                case PayiTunesErrorCodeCloudServicePermissionDenied: {
                        errorDes = @"未授权";
                        break;
                }
                case PayiTunesErrorCodeSelfServiceNetworkFailed:
                case PayiTunesErrorCodeCloudServiceNetworkConnectionFailed: {
                        errorDes = @"网络错误";
                        break;
                }
                case PayiTunesErrorCodeNotLogin: {
                        errorDes = @"未登录";
                        break;
                }
                case PayiTunesErrorCodeRestore: {
                        errorDes = @"正在恢复上次购买...";
                        break;
                }
                case PayiTunesErrorCodePaymentError: {
                        errorDes = @"无效商品";
                        break;
                }
                case PayiTunesErrorCodeLocalRecepitNULL: {
                        errorDes = @"网络错误";
                        break;
                }
                default:
                break;
        }
        return errorDes;
}


NSString *PayiTunesErrorDomain = @"PayiTunesDomain";

//PingxxCompletion pingxxCompletion;

@interface PayManager() < SKPaymentTransactionObserver, SKProductsRequestDelegate >

@property (copy, nonatomic) PayItunesCompletion itunesCompletion;
@property (strong, nonatomic) SKProductsRequest *productsRequest;
@property (assign, nonatomic, getter=isRestoreLastPay) BOOL restoreLastPay;
@property(nonatomic, strong) SKReceiptRefreshRequest *refreshReq;
/**
 *  当前购买的内购物品id
 */
@property (copy, nonatomic) NSString *currentGoodID;
@property (assign, nonatomic) PayiTunesErrorCode errorCode;

/**
 *  当前支付 charge
 */
@property (copy, nonatomic, readwrite) NSString *currentCharge;
@end

@implementation PayManager
+ (instancetype)manager
{
        static PayManager *instance;
        if (!instance)
        {
                instance = [[self alloc] init];
                if ( [SKPaymentQueue canMakePayments] )
                {
                        [[SKPaymentQueue defaultQueue] addTransactionObserver:instance];
                }
        }
        return instance;
}
- (NSString *)currentCharge
{
        if (!_currentCharge)
        {
                _currentCharge = @"未知订单";
        }
        return _currentCharge;
}
#pragma mark - pay method
- (void)payItunes:(NSString *)goodid completion:(PayItunesCompletion)completion
{
        if ( ![self start] )
        {
                NSError *error = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodePaymentNotAllowed userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodePaymentNotAllowed)}];
                if (completion)
                {
                        completion(nil,error,nil);
                }
                return;
        }
//        goodid = [NSString stringWithFormat:@"%@iphone",goodid];
        self.currentCharge = goodid;
        
        if ([self checkAndRestoreFailedPayment:completion])
        {
                return;
        }
        
        
        if (!goodid)
        {
                NSError *error = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodePaymentInvalid userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodePaymentInvalid)}];
                if (completion)
                {
                        completion(nil,error,nil);
                }
                return;
        }
        
        [self buyGoodsAtAppStoreWithGoodsID:@[goodid] completion:completion];
        
}
- (void)restore:(NSString *)goodid completion:(PayItunesCompletion)completion
{
        if (!goodid)
        {
                NSError *error = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodePaymentInvalid userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodePaymentInvalid)}];
                if (completion)
                {
                        completion(nil,error,nil);
                }
                return;
        }
        
        if (completion)
        {
                NSError *error = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodeRestore userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeRestore)}];
                completion(nil,error,nil);
        }
        
        self.currentGoodID = goodid;
        self.itunesCompletion = completion;
        [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (BOOL)isBuy:(NSString *)goodid
{
        if (NULLString(goodid)) {
                return NO;
        }
        NSArray <SKPaymentTransaction *> *transactions = [SKPaymentQueue defaultQueue].transactions;
        
        __block BOOL isHasPayed = NO;
        
        [transactions enumerateObjectsUsingBlock:^(SKPaymentTransaction   * _Nonnull  obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                // 如果是已经付费的，就恢复购买(每次只恢复一个未完成订单)
                if ( obj.transactionState == SKPaymentTransactionStatePurchased && [obj.payment.productIdentifier isEqualToString:goodid])
                {
                        isHasPayed = YES;
                        *stop = YES;
                }
        }];
        return isHasPayed;
}
- (void)cancelCurrentBuy
{
        if (self.productsRequest)
        {
                [self.productsRequest cancel];
        }
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - 内购
- (BOOL)start
{
        return [self startWithTip:YES];
}
- (BOOL)startWithTip:(BOOL)tip
{
        BOOL isCanPay = [SKPaymentQueue canMakePayments];
        
        if (!isCanPay )
        {
                if (tip) {
                        QMUIAlertController *alertVC = [QMUIAlertController alertControllerWithTitle:nil message:@"请先去\"设置-通用-访问限制\"中，开启应用内购买" preferredStyle:(QMUIAlertControllerStyleAlert)];
                        [alertVC addAction:[QMUIAlertAction actionWithTitle:@"知道了" style:(QMUIAlertActionStyleDefault) handler:^(QMUIAlertAction *action) {
                                
                        }]];
                        [alertVC showWithAnimated:YES];
                }
        } else {
                self.refreshReq = [[SKReceiptRefreshRequest alloc] init];
                self.refreshReq.delegate = self;
                [self.refreshReq start];
        }
        
        return isCanPay;
}
/** 检查上次未完成订单 */
- (BOOL)checkAndRestoreFailedPayment:(PayItunesCompletion)completion
{
        NSArray <SKPaymentTransaction *> *transactions = [SKPaymentQueue defaultQueue].transactions;
        
        __block BOOL isHasPayed = NO;
        
        [transactions enumerateObjectsUsingBlock:^(SKPaymentTransaction   * _Nonnull  obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                // 如果是已经付费的，就恢复购买(每次只恢复一个未完成订单)
                if ( obj.transactionState == SKPaymentTransactionStatePurchased && [obj.payment.productIdentifier isEqualToString:self.currentGoodID])
                {
//                        // 如果id无效，说明内购栏目中没有该订单，直接finished
//                        if (![NYPurchaseUIManager isvalideForID:obj.payment.productIdentifier] )
//                        {
//                                [[SKPaymentQueue defaultQueue] finishTransaction:obj];
//                                *stop = YES;
//                        }
//                        // 如果是上次未完成订单，就恢复订单信息
//                        else
//                        {
                                isHasPayed = YES;
                                self.currentGoodID = obj.payment.productIdentifier;
                                
                                if (completion)
                                {
                                        NSError *error = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodeRestore userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeRestore)}];
                                        completion(nil,error,nil);
                                }
                                
                                self.itunesCompletion = completion;
                                [self completeTransaction:obj withError:nil];
                                *stop = YES;
//                        }
                }
                // 其余的就finished掉
                else
                {
                        [[SKPaymentQueue defaultQueue] finishTransaction:obj];
                }
        }];
        
        return isHasPayed;
}


/** 购买物品 */
- (BOOL)buyGoodsAtAppStoreWithGoodsID:(NSArray <NSString *>*)goodsIDs completion:(PayItunesCompletion)completion
{
        /** 购买商品 */
        self.currentGoodID = goodsIDs.firstObject;
        self.itunesCompletion = completion;
        [self requestProductDataUseIdentifier:goodsIDs];
        return YES;
}

//请求商品
- (void)requestProductDataUseIdentifier:(NSArray <NSString *>*)indentifiers
{
        NSLog(@"------------- 请求对应的产品信息--%@ --------------",indentifiers);
        NSSet *productsSet = [NSSet setWithArray:indentifiers];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productsSet];
        self.productsRequest = request;
        request.delegate = self;
        [request start];
}
#pragma mark - ProductsRequest Delegate
/** 请求完成 */
- (void)requestDidFinish:(SKRequest *)request
{
        NSLog(@"------------- 请求对应的产品信息完毕--%@ --------------",request);
}
/** 请求产品信息失败 */
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
        if (self.itunesCompletion)
        {
                NSError *nonGoods = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodeCloudServiceNetworkConnectionFailed userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeCloudServiceNetworkConnectionFailed),@"SKRequestError" : error}];
                self.itunesCompletion(nil,nonGoods,nil);
        }
        NSLog(@"------------- 请求对应的产品信息错误-%@ \n error %@--------------",request,error);
}
/** 收到产品返回信息 */
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
        NSLog(@"--------------收到产品反馈消息---------------------");
        NSArray <SKProduct *>*products = response.products;
        if([products count] == 0)
        {
                NSLog(@"--------------没有商品------------------");
                if (self.itunesCompletion)
                {
                        NSError *nonGoods = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodeStoreProductNotAvailable userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeStoreProductNotAvailable),@"SKProductsResponseDES" : response.description}];
                        self.itunesCompletion(nil,nonGoods,nil);
                }
                return;
        }
        else
        {
                
                NSLog(@"=====================产品信息==================");
                NSLog(@"productID:%@", response.invalidProductIdentifiers);
                NSLog(@"产品付费数量:%d",(int)[products count]);
                
                for (SKProduct *pro in products)
                {
                        NSLog(@"[pro description] %@", [pro description]);
                        NSLog(@"[pro localizedTitle]  %@", [pro localizedTitle]);
                        NSLog(@"[pro localizedDescription]  %@", [pro localizedDescription]);
                        NSLog(@"[pro price]  %@", [pro price]);
                        NSLog(@"[pro productIdentifier]  %@", [pro productIdentifier]);
                        
                        SKPayment *payment = [SKPayment paymentWithProduct:pro];
                        [[SKPaymentQueue defaultQueue] addPayment:payment];
                }
                NSLog(@"=====================产品信息==================");
        }
}


//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
        // 如果不是用户手动购买行为，就不finished  transaction  SKPaymentQueue 在第一次添加observer时，会自动处理上次未完成的订单
        if (!self.currentGoodID)
        {
                NSLog(@"=====================第一次添加Observer恢复上次购买==================\n%@",[queue transactions]);
                return;
        }
        
        for(SKPaymentTransaction *tran in transactions)
        {
                switch (tran.transactionState)
                {
                        case SKPaymentTransactionStatePurchasing:
                        {
                                NSLog(@"商品添加进列表 %@",tran.payment.productIdentifier);
                        }
                                break;
                        case SKPaymentTransactionStatePurchased:
                        {
                                NSLog(@"交易完成  %@",tran.payment.productIdentifier);
                                [self completeTransaction:tran withError:tran.error];
                        }
                                break;
                        case SKPaymentTransactionStateRestored:
                        {
                                NSLog(@"已经购买过产品，未completion  %@",tran.payment.productIdentifier);
                                if ([tran.payment.productIdentifier isEqualToString:self.currentGoodID]) {
                                        [self completeTransaction:tran withError:tran.error];
                                }
                        }
                                break;
                        case SKPaymentTransactionStateFailed:
                        {
                                NSLog(@"交易失败 %@  \n错误信息%@",tran.payment.productIdentifier,tran.error);
                                [self completeTransaction:tran withError:tran.error];
                                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                        }
                                break;
                        case SKPaymentTransactionStateDeferred:
                        {
                                NSLog(@"交易正在进行中  %@",tran.payment.productIdentifier);
                        }
                                break;
                        default:
                                break;
                }
        }
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
        if (self.itunesCompletion) {
                self.itunesCompletion(nil, error,nil);
        }
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
        NSLog(@"恢复已经购买过产品，未completion");
        [queue.transactions enumerateObjectsUsingBlock:^(SKPaymentTransaction * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if ([obj.payment.productIdentifier isEqualToString:self.currentGoodID]) {
                        [self completeTransaction:obj withError:obj.error];
                }
        }];
}
// 交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction withError:(NSError *)error
{
        if (error)
        {
                NSError *payMentError = [NSError errorWithDomain:PayiTunesErrorDomain code:PayiTunesErrorCodeCloudServiceNetworkConnectionFailed userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeCloudServiceNetworkConnectionFailed)}];
                
                if ( [error isKindOfClass:[NSError class]] || [error respondsToSelector:@selector(code)] )
                {
                        NSInteger errorCode = error.code;
                        
                        if (errorCode >= PayiTunesErrorCodeUnknown && errorCode <= PayiTunesErrorCodeLocalRecepitNULL)
                        {
                                payMentError = [NSError errorWithDomain:PayiTunesErrorDomain code:errorCode userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(errorCode)}];
                        }
                }
                
                
                if (self.itunesCompletion)
                {
                        self.itunesCompletion(nil,payMentError,nil);
                }
                NSLog(@" 交易失败  ===  %@",error);
        }
        else
        {
                // 向后台服务器验证票据信息
                NSLog(@"交易结束,验证票据信息");
                // 交易验证
                NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
                NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];
                
                if( !receipt )
                {
                        if (self.itunesCompletion)
                        {
                                NSError *recepitErr = [NSError errorWithDomain:PayiTunesErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeLocalRecepitNULL)}];
                                self.itunesCompletion(nil,recepitErr,nil);
                                return;
                        }
                }
                else
                {
                        [self judgeReceipt:receipt forTrans:transaction];
                }
        }
}
- (void)finished:(SKPaymentTransaction *)trans content:(NSArray *)content withError:(NSError *)error
{
        dispatch_async(dispatch_get_main_queue(), ^{
                
                if (error)
                {
                        if (self.itunesCompletion)
                        {
                                self.itunesCompletion(nil,error,nil);
                        }
                }
                else
                {
                        
                        if (self.itunesCompletion && [self.currentGoodID isEqualToString:trans.payment.productIdentifier])
                        {
                                self.itunesCompletion(content,nil,nil);
                        }
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:trans];
        });
}
- (void)verifyReceipt:(NSData *)receipt purchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)flag
{
        //交易验证
        NSError *error;
        NSDictionary *requestContents = @{
                                          @"receipt-data": [receipt base64EncodedStringWithOptions:0]
                                          };
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                              options:0
                                                                error:&error];
        
        
        //In the test environment, use https://sandbox.itunes.apple.com/verifyReceipt
        //In the real environment, use https://buy.itunes.apple.com/verifyReceipt
        
        NSString *serverString = @"https://buy.itunes.apple.com/verifyReceipt";
        if (flag) {
                serverString = @"https://sandbox.itunes.apple.com/verifyReceipt";
        }
        NSURL *storeURL = [NSURL URLWithString:serverString];
        NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
        [storeRequest setHTTPMethod:@"POST"];
        [storeRequest setHTTPBody:requestData];
        
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                                       
                                       if (connectionError) {
                                               // 无法连接服务器,购买校验失败
                                               [self finished:transaction content:nil withError:connectionError];
                                       } else {
                                               NSError *error;
                                               NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                               if (!jsonResponse) {
                                                       // 苹果服务器校验数据返回为空校验失败
                                                       NSError *recepitErr = [NSError errorWithDomain:PayiTunesErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : ErrorDesForCode(PayiTunesErrorCodeCloudServiceNetworkConnectionFailed)}];
                                                       [self finished:transaction content:nil withError:recepitErr];
                                               }
                                               NSLogDebug(@"----验证结果 %@",jsonResponse);
                                               
                                               // 先验证正式服务器,如果正式服务器返回21007再去苹果测试服务器验证,沙盒测试环境苹果用的是测试服务器
                                               NSString *status = [NSString stringWithFormat:@"%@",jsonResponse[@"status"]];
                                               if (status && [status isEqualToString:@"21007"]) {
                                                       [self verifyReceipt:receipt purchaseWithPaymentTransaction:transaction isTestServer:YES];
                                               } else if(status && [status isEqualToString:@"0"]){
                                                       [self finished:transaction content:nil withError:nil];
                                               }
                                       }
                               }];
}
- (void)judgeReceipt:(NSData *)receipt forTrans:(SKPaymentTransaction *)transaction
{
        /// 支付成功
        // 沙盒 https://sandbox.itunes.apple.com/verifyReceipt
        // 线上 https://buy.itunes.apple.com/verifyReceipt
        
        //base64加密票据
        
        self.itunesCompletion(@[[receipt base64EncodedStringWithOptions:0]], nil, ^(NSError * _Nonnull error) {
                if (!error) {
                        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                }
        });

        // 本地校验，应该放到服务器校验
//        [self verifyReceipt:receipt purchaseWithPaymentTransaction:transaction isTestServer:YES];
}
#pragma mark - UIApplication Delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions
{
        [self startWithTip:NO];
        [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
        return YES;
}

@end
